import Koa from 'koa'
import Router from 'koa-router'
import koabody from 'koa-body'
import serve from 'koa-static'
import mount from 'koa-mount'
import http from 'http'
import ControllerServeHolder from '../controller/controller-serve-holder'
interface IApplicationOptions {
    webContext?: string
    staticPath?: string
    staticPrefix?: string
    port?: number
}
export default class Application extends Koa {
    private contextRouter = new Router()
    private webContext = ''
    private server: http.Server
    private port = 3000
    constructor({ webContext, port, staticPath = '', staticPrefix = '' }: IApplicationOptions ) {
        super()
        this.webContext = webContext || ''
        this.port = port || 3000
        this.use(
            koabody({
                urlencoded: true,
                json: true,
                multipart: true
            })
        )
        if (staticPath) {
            // this.use(serve(staticPath))
            let middle: Koa.Middleware = null
            middle = serve(staticPath)
            if (staticPrefix) {
                middle = mount(staticPrefix, middle)
            }
            if (this.webContext != '') {
                middle = mount(this.webContext, middle)
            }
            this.use(middle)
        }
        this.use(this.contextRouter.routes())
        this.use(this.contextRouter.allowedMethods())

        this.useContext(ControllerServeHolder.makeRouter())

        this.use((ctx, next) => {
            if (!ctx.body) {
                ctx.body = '404'
            }
        })
        let callback = this.callback()
        this.server = http.createServer(callback)
        this.server.listen(this.port)
    }
    public useContext(router: Router | Router.IMiddleware) {
        let mws: Router.IMiddleware[] = []
        if (router instanceof Router) {
            mws = [router.routes(), router.allowedMethods()]
        } else {
            mws = [router]
        }
        if (this.webContext != '') {
            this.contextRouter.use(this.webContext, ...mws)
        } else {
            this.contextRouter.use(...mws)
        }
    }
}
